﻿using System;
using System.Text;
using AgateLib.DisplayLib;
using AiAsteriods.Game.State;
using MType = System.Collections.Generic.Dictionary<AiAsteriods.Game.Entities.Agent.ActionType, float>;

namespace AiAsteriods.Game.Entities.Agent {
  static class DecidePathFinding {
    private static float rl;
    private static float rr;
    private static float ra;
    private static float rf;
    private static float rs;
    private static FontSurface fontValues = new FontSurface("Verdana", 9);
    private static FontSurface fontDecision = new FontSurface("Verdana", 9);

    public static ActionType Decide(int playerNum, GameStateAbstract gs) {
      ActionType maxAction;
      var val = new MType();

      StateGrid.CalcGrid(playerNum, Global.GameStart.CurrentState);
      StateGrid.DisplayGrid(playerNum);

      maxAction = ActionType.BRAKE;
      float maxF = float.MinValue;
      val = F(playerNum);
      StringBuilder values = new StringBuilder();

      foreach (var v in val) {
        if (v.Value > maxF) {
          maxF = v.Value;
          maxAction = v.Key;
        }
        values.Append(String.Format("{0}:{1:00.000}, ", v.Key, v.Value));
      }
      values.Remove(values.Length - 2, 2);
      fontValues.DrawText(20, 55, "<" + values.ToString() + ">");
      fontDecision.DrawText(20, 75, "MaxAction: " + maxAction);

      return maxAction;
    }

    private static MType F(int playerNum) {
      var values = new MType();
      foreach (ActionType action in Enum.GetValues(typeof(ActionType)))
        values[action] = 0f;

      //values[ActionType.ORIGIN] = 0.1f;
      //values[ActionType.BRAKE] = 1;

      if (Global.GameStart.Config.UseH)
        values = H(playerNum, values);

      if (Global.GameStart.Config.UseG)
        values = G(values);
      
      if (Global.GameStart.Config.UseU)
        values = U(values);

      return values;
    }

    private static MType H(int playerNum, MType values) {
      StateGrid.GetRegionCounts(playerNum, out rl, out rr, out ra, out rf, out rs);
      float maxAmount = ((GameState)Global.GameStart.CurrentState).NumEnemies * PosF.MaxDist + float.Epsilon;

      values[ActionType.ACCEL] += ra / maxAmount;
      values[ActionType.BRAKE] += 1.0f / maxAmount;
      values[ActionType.FLEE] += rf / maxAmount;
      values[ActionType.LEFT] += rl / maxAmount;
      values[ActionType.RIGHT] += rr / maxAmount;
      values[ActionType.SHOOT] += (float)Math.Pow(rs / maxAmount, 1);

      return values;
    }

    private static MType G(MType values) {
      MNode root = new MNode();
      root = MNode.Build(root);

      //fontDecision.DrawText(0, 250, String.Format("subnodes: {0}", root.CountSubNodes()));

      float[] childScores = root.GetChildScores();

      for (int i = 0; i < MNode.numActions; i++)
        values[(ActionType)i] += childScores[i] / MNode.MaxDepth;

      for (int i = MNode.numActions; i < 6; i++)
        values[(ActionType)i] += 1.0f / MNode.MaxDepth;

      return values;
    }

    private static MType U(MType values) {
      values[ActionType.ACCEL] *= 1.4f;
      values[ActionType.BRAKE] *= 1.0f;
      values[ActionType.FLEE] *= 1.2f;
      values[ActionType.LEFT] *= 0.8f;
      values[ActionType.RIGHT] *= 0.8f;
      values[ActionType.SHOOT] *= 1.2f;
      values[ActionType.ORIGIN] *= 0.0f;

      return values;
    }
  }
}
